﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace PracticalExamples.鼠标选框
{
    /// <summary>
    /// MouseBoxSelect.xaml 的交互逻辑
    /// </summary>
    public partial class MouseBoxSelect : Window
    {
        private Border currentBoxSelectedBorder = null;
        private bool isCanMove = false;//鼠标是否移动
        private Point tempStartPoint;

        private List<Rectangle> selectRactangles = new List<Rectangle>();

        //public RoutedCommand ResetCommond = new RoutedCommand("Reset", typeof(MouseBoxSelect));
        public MouseBoxSelect()
        {
            InitializeComponent();
        }

        public static List<T> GetChildObjects<T>(System.Windows.DependencyObject obj) where T : System.Windows.FrameworkElement
        {
            System.Windows.DependencyObject child = null;
            List<T> childList = new List<T>();
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                child = VisualTreeHelper.GetChild(obj, i);
                if (child is T)
                {
                    childList.Add((T)child);
                }
                childList.AddRange(GetChildObjects<T>(child));//递归获取子控件对象
            }
            return childList;
        }

        private void MainCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (currentBoxSelectedBorder != null)
            {
                //获取选框矩形位置
                Point tempEndPoint = e.GetPosition(this.mainCanvas);
                Rect tempRect = new Rect(tempStartPoint, tempEndPoint);

                //获取子控件
                List<Rectangle> childList = GetChildObjects<Rectangle>(this.mainCanvas);
                foreach (var child in childList)
                {
                    Rect childRect = new Rect(Canvas.GetLeft(child), Canvas.GetTop(child), child.Width, child.Height);
                    
                    if (childRect.IntersectsWith(tempRect))
                    {
                        child.Opacity = 0.4;
                        selectRactangles.Add(child);
                    }
                }
                this.mainCanvas.Children.Remove(currentBoxSelectedBorder);
                currentBoxSelectedBorder = null;

            }
            else if(currentBoxSelectedBorder == null && Keyboard.IsKeyDown(Key.LeftCtrl))
            {
                //ctr+鼠标左键点击，还原方块透明度
                //获取子控件
                List<Rectangle> childList = GetChildObjects<Rectangle>(this.mainCanvas);
                foreach (var child in childList)
                {
                    Rect childRect = new Rect(Canvas.GetLeft(child), Canvas.GetTop(child), child.Width, child.Height);

                    if (PointInRect(tempStartPoint, childRect))
                    {
                        child.Opacity = 1;
                        selectRactangles.Remove(child);
                    }
                }
            }
            isCanMove = false;
        }

        private void MainCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            isCanMove = true;
            tempStartPoint = e.GetPosition(this.mainCanvas);
            
        }

        private void MainCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (isCanMove)
            {
                Point tempEndPoint = e.GetPosition(this.mainCanvas);
                //绘制
                DrawMultiselectBorder(tempStartPoint, tempEndPoint);
            }
        }
        /// <summary>
        /// 绘制矩形选框
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        private void DrawMultiselectBorder(Point start,Point end)
        {
            if (currentBoxSelectedBorder == null)
            {
                currentBoxSelectedBorder = new Border();
                currentBoxSelectedBorder.Background = new SolidColorBrush(Colors.Orange);
                currentBoxSelectedBorder.Opacity = 0.4;
                currentBoxSelectedBorder.BorderThickness = new Thickness(2);
                currentBoxSelectedBorder.BorderBrush = new SolidColorBrush(Colors.Green);
                Canvas.SetZIndex(currentBoxSelectedBorder, 100);
                this.mainCanvas.Children.Add(currentBoxSelectedBorder);
            }
            //计算选框的大小
            currentBoxSelectedBorder.Width = Math.Abs(end.X - start.X);
            currentBoxSelectedBorder.Height = Math.Abs(end.Y - start.Y);

            //用于确定选框在Canvas中的位置。
            if (end.X - start.X >= 0)
            {
                Canvas.SetLeft(currentBoxSelectedBorder, start.X);
            }
            else
            {
                Canvas.SetLeft(currentBoxSelectedBorder, end.X);
            }
            if (end.Y - start.Y >= 0)
            {
                Canvas.SetTop(currentBoxSelectedBorder, start.Y);
            }
            else
            {
                Canvas.SetTop(currentBoxSelectedBorder, end.Y);
            }
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (selectRactangles.Count==0)
            {
                e.CanExecute = false;
            }
            else
            {
                e.CanExecute = true;
            }

            e.Handled = true;
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            foreach (var child in selectRactangles)
            {
                child.Opacity = 1;
            }
            selectRactangles.Clear();
            e.Handled = true;
        }
        /// <summary>
        /// 用于判断点是否在在矩形内部
        /// </summary>
        /// <param name="point"></param>
        /// <param name="rect"></param>
        /// <returns></returns>
        private bool PointInRect(Point point,Rect rect)
        {
            double x = point.X - rect.Left;
            double y = point.Y - rect.Top;
            if (0<x && x<rect.Width && 0<y && y<rect.Height)
            {
                return true;
            }
            return false;
        }
    }
}
